package layer_model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import dto.Layer;
import dto.Sample;
import dxo.SampleTo;
import evaluation.EvaluationTool;

public class GreedyLayerModel implements LayerModel {
	
	private int [] model;
	private double [] value;

	@Override
	public int test(Sample sample) {
		int [] layers = sample.getLayers();
		int k = 0;
		for(; k < model.length; k++) {
			if(layers[model[k]] == 0) {
				break;
			}
		}
		return k;
	}

	@Override
	public void train(List<Sample> samples) {
		
		Set<Integer> set = new HashSet<Integer>();
		int nLayer = samples.get(0).getLayers().length;
		for(int i = 0; i < nLayer; i++) {
			set.add(i);
		}
		
		List<Integer> modeled = new ArrayList<Integer>();
		List<Double> valued = new ArrayList<Double>();
		while(!set.isEmpty()) {
			List<Integer> labelList = SampleTo.toLabel(samples);
			List<Layer> layers = SampleTo.toLayer(samples);
			
			int bestLayer = -1;
			double bestScore = -1.0;
			
			for(int l : set) {
				double score = getScore(layers.get(l), labelList);
				if(score > bestScore) {
					bestScore = score;
					bestLayer = l;
				}
			}
			modeled.add(bestLayer);
			valued.add(bestScore);
			set.remove(bestLayer);
		}
		
		model = new int[modeled.size()];
		value = new double[modeled.size()];
		for(int i = 0; i < modeled.size(); i++) {
			model[i] = modeled.get(i);
			value[i] = valued.get(i);
		}
	}

	protected double getScore(Layer layer, List<Integer> labelList) {
		int [] plist = layer.getPrediction();
		List<Integer> predictList = new ArrayList<Integer>(plist.length);
		for(int p : plist) {
			predictList.add(p);
		}
		Map<String, Double> result = EvaluationTool.evaluate(labelList, predictList);
		return result.get("info");
	}
	
	protected List<Sample> filterSample(List<Sample> samples, Layer layer) {
		int [] predictions = layer.getPrediction();
		Iterator<Sample> sItr = samples.iterator();
		
		List<Sample> filtered = new LinkedList<Sample>();
		for(int prediction : predictions) {
			Sample sample = sItr.next();
			if(prediction == 1) {
				filtered.add(sample);
			}
		}
		
		return filtered;
	}

	@Override
	public String dump() {
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < model.length; i++) {
			sb.append(model[i] + "(" + value[i] + ") ");
		}
		return sb.toString().trim();
	}
}
